home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 19 / Amiga Plus Leser CD 19.iso / Tools / Freeware / Swf_Player / Lib / graphic16.cc < prev    next >
Encoding:
C/C++ Source or Header  |  2002-11-17  |  15.8 KB  |  659 lines

  1. ////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. // 
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. // 
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. // 
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. // 
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //  
  22.  
  23. #include "swf.h"
  24.  
  25. #include "graphic16.h"
  26.  
  27. extern unsigned char SQRT[];
  28.  
  29. #define FULL_AA
  30.  
  31. #define PRINT 0
  32.  
  33. typedef unsigned short TYPE;
  34.  
  35. GraphicDevice16::GraphicDevice16(FlashDisplay *fd) : GraphicDevice(fd)
  36. {
  37. }
  38.  
  39. long
  40. GraphicDevice16::allocColor(Color color)
  41. {
  42.     return (color.red >> 3)<<11 | (color.green>>2)<<5 | (color.blue>>3);
  43. }
  44.  
  45. void
  46. GraphicDevice16::clearCanvas()
  47. {
  48.     TYPE  pixel;
  49.     TYPE *point,*p;
  50.     long                 h, w,n;
  51.  
  52.     if (!bgInitialized) return;
  53.  
  54.     pixel = allocColor(backgroundColor);
  55.  
  56.     point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin;
  57.     w = clip_rect.xmax - clip_rect.xmin;
  58.     h = clip_rect.ymax - clip_rect.ymin;
  59.  
  60.     while (h--) {
  61.         p = point;
  62.         n = w;
  63.         while (n--) {
  64.             *p++ = pixel;
  65.         }
  66.  
  67.         point = (TYPE *)((char *)point + bpl);
  68.     }
  69.  
  70.     flashDisplay->flash_refresh = 1;
  71.     flashDisplay->clip_x = clip_rect.xmin;
  72.     flashDisplay->clip_y = clip_rect.ymin;
  73.     flashDisplay->clip_width  = clip_rect.xmax-clip_rect.xmin;
  74.     flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin;
  75. }
  76.  
  77. #define RED_MASK   0xF800
  78. #define GREEN_MASK 0x07E0
  79. #define BLUE_MASK  0x001F
  80.  
  81. /* alpha = 0 : select c1, alpha = 255 select c2 */
  82. static inline unsigned long
  83. mix_alpha(unsigned long c1, 
  84.                                       unsigned long c2, int alpha)
  85. {
  86.     long r1,r2,r;
  87.     long g1,g2,g;
  88.     long b1,b2,b;
  89.  
  90.     r1 = c1 & RED_MASK;
  91.     r2 = c2 & RED_MASK;
  92.     r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK;
  93.  
  94.     g1 = c1 & GREEN_MASK;
  95.     g2 = c2 & GREEN_MASK;
  96.     g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK;
  97.  
  98.     b1 = c1 & BLUE_MASK;
  99.     b2 = c2 & BLUE_MASK;
  100.     b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK;
  101.  
  102.     return (r|g|b);
  103. }
  104.  
  105. void
  106. GraphicDevice16::fillLineAA(FillStyleDef *f, long y, long start, long end)
  107. {
  108.     register long   n;
  109.     TYPE *line;
  110.     TYPE *point,pixel;
  111.     unsigned int alpha, start_alpha,end_alpha;
  112.     
  113.     if (clip(y,start,end)) return;
  114.     
  115.     line = (TYPE *)(canvasBuffer + bpl*y);
  116.     
  117.     alpha = f->color.alpha;
  118.     pixel = f->color.pixel;
  119.     
  120.     if (alpha == ALPHA_OPAQUE) {
  121.  
  122.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  123.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  124.         
  125.         start >>= FRAC_BITS;
  126.         end >>= FRAC_BITS;
  127.         
  128.         point = &line[start];
  129.  
  130.         if (start == end) {
  131.             *point = mix_alpha(*point, pixel, start_alpha + end_alpha - 255);
  132.         } else {
  133.             n = end-start;
  134.             if (start_alpha < 255) {
  135.                 *point = mix_alpha(*point, pixel, start_alpha);
  136.                 point++;
  137.                 n--;
  138.             }
  139.             while (n > 0) {
  140.                 *point = pixel;
  141.                 point++;
  142.                 n--;
  143.             }
  144.             if (end_alpha > 0) {
  145.                 *point = mix_alpha(*point, pixel, end_alpha);
  146.             }
  147.         }
  148.     } else {
  149.  
  150.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  151.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  152.  
  153.         start >>= FRAC_BITS;
  154.         end >>= FRAC_BITS;
  155.         
  156.         point = &line[start];
  157.         
  158.         if (start == end) {
  159.             *point = mix_alpha(*point, pixel, 
  160.                                ((start_alpha + end_alpha - 255) * alpha) >> 8);
  161.         } else {
  162.             n = end-start;
  163.             if (start_alpha < 255) {
  164.                 *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8);
  165.                 point++;
  166.                 n--;
  167.             }
  168.             while (n > 0) {
  169.                 *point = mix_alpha(*point, pixel, alpha);
  170.                 point++;
  171.                 n--;
  172.             }
  173.             if (end_alpha > 0) {
  174.                 *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8);
  175.             }
  176.         }
  177.     }
  178. }
  179.  
  180. void
  181. GraphicDevice16::fillLine(FillStyleDef *f, long y, long start, long end)
  182. {
  183.     register long   n;
  184.         TYPE *line,*point;
  185.         TYPE pixel;
  186.         unsigned int alpha;
  187.  
  188.     if (clip(y,start,end)) return;
  189.  
  190.         start >>= FRAC_BITS;
  191.         end >>= FRAC_BITS;
  192.  
  193.     line = (TYPE *)(canvasBuffer + bpl*y);
  194.     point = &line[start];            
  195.     n = end-start;                
  196.         pixel = f->color.pixel;
  197.         alpha = f->color.alpha;
  198.         if (alpha == ALPHA_OPAQUE) {
  199.             while (n--) { 
  200.         *point = pixel;
  201.         point++;            
  202.             }
  203.         } else {
  204.             while (n--) { 
  205.         *point = mix_alpha(*point, pixel, alpha);
  206.         point++;            
  207.             }
  208.         }
  209. }
  210.  
  211. void
  212. GraphicDevice16::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
  213. {
  214.     int n;
  215.     long x1,y1,dx,dy;
  216.     Matrix *m = &f->bitmap_matrix;
  217.     Bitmap *b = f->bitmap;
  218.     unsigned char *pixels;
  219.     TYPE *p;
  220.     Color *cmap;
  221.     long pixbpl;
  222.     TYPE pixel;
  223.     int offset;
  224.     unsigned char *alpha_table;
  225.  
  226.     /* safety test) */
  227.     if (!b) return;
  228.  
  229.     if (clip(y,start,end)) return;
  230.     
  231.     start /= FRAC;
  232.     end /= FRAC;
  233.     n = end - start;
  234.     p = (TYPE *) (this->canvasBuffer + this->bpl*y + start * 2);
  235.     
  236.     /* the coordinates in the image are normalized to 16 bits */
  237.     x1 = (long) (m->a * start + m->b * y + m->tx);
  238.     y1 = (long) (m->c * start + m->d * y + m->ty);
  239.     dx = (long) (m->a);
  240.     dy = (long) (m->c);
  241.     
  242.     pixels = b->pixels;
  243.     pixbpl = b->bpl;
  244.     cmap = f->cmap;
  245.  
  246.     if (b->alpha_buf == NULL) {
  247.         while (n) {
  248.             if (x1 >= 0 && y1 >= 0 && 
  249.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  250.                 
  251.                 pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel;
  252.                 *p = pixel;
  253.             }
  254.             x1 += dx;
  255.             y1 += dy;
  256.             p++;
  257.             n--;
  258.         }
  259.     } else if (f->alpha_table) {
  260.         alpha_table = f->alpha_table;
  261.         while (n) {
  262.             if (x1 >= 0 && y1 >= 0 && 
  263.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  264.                 
  265.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  266.                 pixel = cmap[pixels[offset]].pixel;
  267.                 *p = mix_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]);
  268.             }
  269.             x1 += dx;
  270.             y1 += dy;
  271.             p++;
  272.             n--;
  273.         }
  274.     } else {
  275.         while (n) {
  276.             if (x1 >= 0 && y1 >= 0 && 
  277.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  278.                 
  279.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  280.                 pixel = cmap[pixels[offset]].pixel;
  281.                 *p = mix_alpha(*p, pixel, b->alpha_buf[offset]);
  282.             }
  283.             x1 += dx;
  284.             y1 += dy;
  285.             p++;
  286.             n--;
  287.         }
  288.     }
  289. }
  290.  
  291. void
  292. GraphicDevice16::fillLineLG(Gradient *grad, long y, long start, long end)
  293. {
  294.     long dr,r,v,r2;
  295.     register long n;
  296.     TYPE *line;
  297.     TYPE *point;
  298.         Color *cp,*ramp;
  299.         Matrix *m = &grad->imat;
  300.         unsigned int start_alpha,end_alpha;
  301.  
  302.     if (clip(y,start,end)) return;
  303.  
  304.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  305.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  306.         
  307.     start /= FRAC;
  308.     end /= FRAC;
  309.  
  310.     n = end-start;
  311.  
  312.         r = (long) (m->a * start + m->b * y + m->tx);
  313.         dr = (long) (m->a);
  314.  
  315.         ramp = grad->ramp;
  316.  
  317.         line = (TYPE *)(canvasBuffer + bpl*y);
  318.     point = &line[start];    
  319.  
  320.         r2 = r + n * dr;
  321.         if ( ((r | r2) & ~255) == 0 ) {
  322.             if (!grad->has_alpha) {
  323. #ifdef FULL_AA
  324.         if (start_alpha < 255) {
  325.                     v = r>>16;
  326.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
  327.                     point++;
  328.                     r += dr;
  329.             n--;
  330.         }
  331. #endif /* FULL_AA */
  332.                 while (n>0) {
  333.                     v = r>>16;
  334.                     *point = (TYPE)ramp[v].pixel;    
  335.                     point++;                
  336.                     r += dr;                
  337.             n--;
  338.                 }
  339. #ifdef FULL_AA
  340.         if (end_alpha > 0) {
  341.                     v = r>>16;
  342.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
  343.         }
  344. #endif /* FULL_AA */
  345.             } else {
  346.                 while (n--) {
  347.                     v = r>>16;
  348.                     cp = &ramp[v];
  349.                     *point = mix_alpha(*point, cp->pixel, cp->alpha);
  350.                     point++;
  351.                     r += dr;
  352.                 }
  353.             }
  354.         } else {
  355.             if (!grad->has_alpha) {
  356. #ifdef FULL_AA
  357.         if (start_alpha < 255) {
  358.                     v = r>>16;
  359.                     if (v < 0) v = 0;
  360.                     else if (v > 255) v = 255;
  361.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
  362.                     point++;
  363.                     r += dr;
  364.             n--;
  365.         }
  366. #endif /* FULL_AA */
  367.                 while (n>0) {
  368.                     v = r>>16;
  369.                     if (v < 0) v = 0;
  370.                     else if (v > 255) v = 255;
  371.                     *point = (TYPE)ramp[v].pixel;    
  372.                     point++;                
  373.                     r += dr;                
  374.             n--;
  375.                 }
  376. #ifdef FULL_AA
  377.         if (end_alpha > 0) {
  378.                     v = r>>16;
  379.                     if (v < 0) v = 0;
  380.                     else if (v > 255) v = 255;
  381.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
  382.         }
  383. #endif /* FULL_AA */
  384.             } else {
  385.                 while (n--) {
  386.                     v = r>>16;
  387.                     if (v < 0) v = 0;
  388.                     else if (v > 255) v = 255;
  389.                     cp = &ramp[v];
  390.                     *point = mix_alpha(*point, cp->pixel, cp->alpha);
  391.                     point++;
  392.                     r += dr;
  393.                 }
  394.             }
  395.         }
  396. }
  397.  
  398. void
  399. GraphicDevice16::fillLineRG(Gradient *grad, long y, long start, long end)
  400. {
  401.     long X,dx,r,Y,dy;
  402.     long dist2;
  403.     register long   n;
  404.         Color *cp,*ramp;
  405.     TYPE *line;                            
  406.     TYPE *point;                            
  407.         Matrix *m = &grad->imat;
  408.         unsigned int start_alpha,end_alpha;
  409.  
  410.     if (clip(y,start,end)) return;
  411.  
  412.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  413.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  414.         
  415.     start /= FRAC;
  416.     end /= FRAC;
  417.  
  418.     n = end-start;
  419.         
  420.         X = (long) (m->a * start + m->b * y + m->tx);
  421.         Y = (long) (m->c * start + m->d * y + m->ty);
  422.         dx = (long) (m->a);
  423.         dy = (long) (m->c);
  424.  
  425.         ramp = grad->ramp;
  426.                                     
  427.     line = (TYPE *)(canvasBuffer + bpl*y);
  428.     point = &line[start];
  429.                  
  430.         if (!grad->has_alpha) {
  431. #ifdef FULL_AA
  432.         if (start == end) {
  433.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  434.             if ((unsigned long)dist2 >= 65536) {
  435.                 r = 255;                    
  436.             } else {                        
  437.                 r = SQRT[dist2];    
  438.             }
  439.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255);
  440.         } else {
  441.             if (start_alpha < 255) {
  442.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  443.             if ((unsigned long)dist2 >= 65536) {
  444.                 r = 255;                    
  445.             } else {                        
  446.                 r = SQRT[dist2];    
  447.             }
  448.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha);
  449.             point++;
  450.             X += dx;                        
  451.             Y += dy;                        
  452.             n--;
  453.             }
  454. #endif /* FULL_AA */
  455.             while (n>0) {                    
  456.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  457.             if ((unsigned long)dist2 >= 65536) {
  458.                 r = 255;                    
  459.             } else {                        
  460.                 r= SQRT[dist2];    
  461.             }
  462.             *point = (TYPE)ramp[r].pixel;
  463.             point++;                     
  464.             X += dx;                        
  465.             Y += dy;                        
  466.             n--;
  467.             }        
  468. #ifdef FULL_AA
  469.             if (end_alpha > 0) {
  470.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  471.             if ((unsigned long)dist2 >= 65536) {
  472.                 r = 255;                    
  473.             } else {                        
  474.                 r= SQRT[dist2];    
  475.             }
  476.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, end_alpha);
  477.             }
  478.         }
  479. #endif /* FULL_AA */
  480.  
  481.         } else {
  482.             while (n--) {                    
  483.         dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  484.         if ((unsigned long)dist2 >= 65536) {
  485.                     r = 255;                    
  486.         } else {                        
  487.                     r= SQRT[dist2];    
  488.         }
  489.                 cp = &ramp[r];
  490.         *point = mix_alpha(*point, cp->pixel, cp->alpha);
  491.         point++;
  492.         X += dx;                        
  493.         Y += dy;                        
  494.             }        
  495.         }
  496. }
  497.  
  498. void
  499. GraphicDevice16::drawLine(long x1, long y1, long x2, long y2, long width)
  500. {
  501.     int n,adr,dx,dy,sx,color;
  502.     register int a;
  503.     register TYPE *pp;
  504.     int alpha;
  505.  
  506.     x1 = (x1) >> FRAC_BITS;
  507.     y1 = (y1) >> FRAC_BITS;
  508.     x2 = (x2) >> FRAC_BITS;
  509.     y2 = (y2) >> FRAC_BITS;
  510.     
  511.     if (y1 > y2 || (y1 == y2 && x1 > x2)) {
  512.         long tmp;
  513.  
  514.         tmp=x1;
  515.         x1=x2;
  516.         x2=tmp;
  517.  
  518.         tmp=y1;
  519.         y1=y2;
  520.         y2=tmp;
  521.     }
  522.  
  523.     if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return;
  524.     if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return;
  525.     if (x1 == x2 && y1 == y2) return;    // Bad !!!
  526.  
  527.     if (y1 < clip_rect.ymin && y1 != y2) {
  528.     x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1);
  529.     y1 = clip_rect.ymin;
  530.     }
  531.  
  532.     if (y2 > clip_rect.ymax && y1 != y2) {
  533.     x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1);
  534.     y2 = clip_rect.ymax;
  535.     }
  536.  
  537.     if (x1 < x2) {
  538.         if (x1 < clip_rect.xmin && x1 != x2) {
  539.         y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1);
  540.         x1 = clip_rect.xmin;
  541.         }
  542.  
  543.         if (x2 > clip_rect.xmax && x1 != x2) {
  544.         y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1);
  545.         x2 = clip_rect.xmax;
  546.         }
  547.     }
  548.  
  549.     if (x1 > x2) {
  550.         if (x2 < clip_rect.xmin && x2 != x1) {
  551.         y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2);
  552.         x2 = clip_rect.xmin;
  553.         }
  554.  
  555.         if (x1 > clip_rect.xmax && x2 != x1) {
  556.         y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2);
  557.         x1 = clip_rect.xmax;
  558.         }
  559.     }
  560.  
  561.     // Check again
  562.     if (x1 == x2 && y1 == y2) return;
  563.     if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return;
  564.     if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return;
  565.     if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return;
  566.     if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return;
  567.  
  568.     sx=bpl >> 1;
  569.     adr=(y1 * sx + x1);
  570.     pp = (TYPE *)canvasBuffer + adr;
  571.     
  572.     dx = x2 - x1;
  573.     dy = y2 - y1;
  574.  
  575.     color = allocColor(foregroundColor);
  576.     alpha = foregroundColor.alpha;
  577.  
  578.     if (alpha == ALPHA_OPAQUE) {
  579.  
  580. #define PUTPIXEL()                 \
  581.   {                        \
  582.       *pp=color;                        \
  583.   }
  584.  
  585. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  586.     n=dx;\
  587.     a=2*dy-dx;\
  588.     dy=2*dy;\
  589.     dx=2*dx-dy;\
  590.      do {\
  591.       PUTPIXEL();\
  592.             if (a>0) { pp+=(inc_1); a-=dx; }\
  593.             else { pp+=(inc_2); a+=dy; }\
  594.      } while (--n >= 0);
  595.  
  596. /* fin macro */
  597.  
  598.   if (dx == 0 && dy == 0) {
  599.     PUTPIXEL();
  600.   } else if (dx > 0) {
  601.     if (dx >= dy) {
  602.       DRAWLINE(dx, dy, sx + 1, 1);
  603.     } else {
  604.       DRAWLINE(dy, dx, sx + 1, sx);
  605.     }
  606.   } else {
  607.     dx = -dx;
  608.     if (dx >= dy) {
  609.       DRAWLINE(dx, dy, sx - 1, -1);
  610.     } else {
  611.       DRAWLINE(dy, dx, sx - 1, sx);
  612.     }
  613.   }
  614.  
  615.  
  616. #undef DRAWLINE
  617. #undef PUTPIXEL
  618.     } else {
  619. #define PUTPIXEL()                 \
  620.   {                        \
  621.       *pp=mix_alpha(*pp,color,alpha);            \
  622.   }
  623.  
  624. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  625.     n=dx;\
  626.     a=2*dy-dx;\
  627.     dy=2*dy;\
  628.     dx=2*dx-dy;\
  629.      do {\
  630.       PUTPIXEL();\
  631.             if (a>0) { pp+=(inc_1); a-=dx; }\
  632.             else { pp+=(inc_2); a+=dy; }\
  633.      } while (--n >= 0);
  634.  
  635. /* fin macro */
  636.  
  637.   if (dx == 0 && dy == 0) {
  638.     PUTPIXEL();
  639.   } else if (dx > 0) {
  640.     if (dx >= dy) {
  641.       DRAWLINE(dx, dy, sx + 1, 1);
  642.     } else {
  643.       DRAWLINE(dy, dx, sx + 1, sx);
  644.     }
  645.   } else {
  646.     dx = -dx;
  647.     if (dx >= dy) {
  648.       DRAWLINE(dx, dy, sx - 1, -1);
  649.     } else {
  650.       DRAWLINE(dy, dx, sx - 1, sx);
  651.     }
  652.   }
  653.  
  654.  
  655. #undef DRAWLINE
  656. #undef PUTPIXEL
  657.     }
  658. }
  659.